#ifndef MAZE_H
#define MAZE_H

#include "AIRoom.h"
#include "Graph.h"
#include "GraphNode.h"
#include "MazeTypes.h"
#include "GameObject.h"
#include "EventHandler.h"
#include "EventPoller.h"
#include "Graph.h"

#include <SDL_thread.h>
#include <stack>
#include <vector>
#include <map>

class Maze : public GameObject, public EventHandler
{
public:
	Maze();
	~Maze();

	void Update() override;
	void Draw() override;
	void DrawMiniMapElements() override;
	void DrawMiniMapColourPick() override;
	void DrawColourPick() override;

	bool Generate(int numOfRooms, const D3DXVECTOR2& size, const D3DXVECTOR3& cellSize);

	virtual bool Load(File* f);
	virtual const char* GetTypeName() const override;
	virtual void OnKeyDownEvent(const WPARAM& event) override;
	virtual void OnKeyUpEvent(const WPARAM& event) override;
	virtual void OnMouseMotionEvent(const LPARAM& event) override;
	virtual void OnMouseButtonDownEvent(const MSG& event) override;
	virtual void OnMouseButtonUpEvent(const MSG& event) override;
	
	// collision tests
	bool CheckCollision(OOBB3& oobb);

	const D3DXVECTOR3& GetCellSize() const;
	const D3DXVECTOR2& GetGridSize() const;
	const D3DXVECTOR3& GetPos() const;

	void UpdateAgents();
	void DrawAgents();

	const D3DXVECTOR3& GetCellPos(const CellPosition& cp) const;
	RoomsCells& GetRoomCells();
private:
	//void CalcCollision(const CellPosition& cellPos, OOBB3& oobb
	void CalculateCellsInVisibleRange();
	void CalculateCurrentCell();
	void GeneratePathsDFS();
	void CalculateDoorCells();
	void CalculateWallCells();
	void CalculateRoomEdges();

	void CalculateToDrawWalls();
	void CalculateToDrawPaths();

	void DrawVerticalWall(const D3DXVECTOR3& pos);
	void DrawHorizontalWall(const D3DXVECTOR3& pos);
	void DrawVerticalDoor(const D3DXVECTOR3& pos);
	void DrawHorizontalDoor(const D3DXVECTOR3& pos);

	void DrawSouthWall(const D3DXVECTOR3& pos);
	void DrawWestWall(const D3DXVECTOR3& pos);
	void DrawSouthDoor(const D3DXVECTOR3& pos);
	void DrawWestDoor(const D3DXVECTOR3& pos);

	void DrawWall(const CellPosition& cell);	
	void DrawCell(const CellPosition& cell);

	void DrawCameraPositionOrtho();

	// path find algorithm functions
	void CalculateAStar(const CellPosition& pickedCell);
	Edges GetEdgeList(const CellPosition& cell);
	float CalculateHeuristic(const CellPosition& start, const CellPosition& end);
private:
	std::vector<CellPosition> m_connectingRooms;
	std::map<CellPosition, CellPosition> m_connectedCells;
	std::map<int, int> m_connectedRooms;
	std::map<int, RoomSize> m_sizeOfRooms;
	std::vector<CellPosition> m_roomEdges;
	std::vector<CellPosition> m_doorsForDrawing;
	RoomsCells m_roomsCells;
	RoomsCells m_roomCells;
	std::stack<CellPosition> m_cellsInVisibleRange;
	std::vector<CellPosition> m_wallCells;
	std::vector<CellPosition> m_miniMapDrawCells;
	RoomsCells m_surroundingRoomsCells;
	std::vector<D3DXVECTOR4> m_roomColours;

	// to draw path/wall cells
	std::vector<CellPosition> m_toDrawWalls;
	std::vector<CellPosition> m_toDrawPaths;

	int m_numOfRooms;
	
	// change this to a transformation matrix later
	D3DXVECTOR3 m_size;
	D3DXVECTOR3 m_cellSize;

	Grid m_grid;
	std::map<D3DXVECTOR4, CellPosition> m_cellColours;
	std::map<CellPosition, D3DXVECTOR4> m_cellColoursOp;
	D3DXVECTOR2 m_gridSize;

	int m_seed;
	//std::vector<Wall> m_verticalWalls;
	//std::vector<Wall> m_horizontalWalls;

	std::map<CellPosition, bool> m_verticalWalls;
	std::map<CellPosition, bool> m_horizontalWalls;

	D3DXVECTOR3 m_position;
	D3DXMATRIX m_world;
	std::map<CellPosition, CellWall> m_cellWalls;

	// south wall draw vars	
	//ID3D11Buffer* m_pVertexBufferSouth;
	//ID3D11Buffer* m_pIndexBufferSouth;
	//ID3D11Buffer* m_pConstantBufferSouth;
	// west wall draw vars	
	//ID3D11Buffer* m_pVertexBufferWest;
	//ID3D11Buffer* m_pIndexBufferWest;
	//ID3D11Buffer* m_pConstantBufferWest;
	
	ConstantBuffer m_cbSouth;

	D3DXMATRIX m_worldSouth;

	int m_numOfIndicesSouth;
	std::string m_shaderNameSouth;
	D3DXVECTOR4 m_colourSouth;


	
	ConstantBuffer m_cbWest;

	D3DXMATRIX m_worldWest;

	int m_numOfIndicesWest;
	std::string m_shaderNameWest;
	D3DXVECTOR4 m_colourWest;
	
	MazeDisplayInfo m_displayInfo;

	std::vector<JoiningDoorCells> m_doorCells;
	CellPosition m_currentCell;

	bool m_canCheckForPick;
	int m_mouseX;
	int m_mouseY;
	D3DXVECTOR4 m_pickedColour;
	
	std::set<CellPosition> m_trail;
	D3DXVECTOR3 m_miniMapElesScale;
};

#endif //MAZE_H